//
// Created by Zhang on 2022/5/12.
//
//extra q1
#include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

class CShape {
public:
    virtual float Area() = 0;

    virtual void SetData(float a, float b, float c) = 0;

    virtual void SetData(float a, float b) = 0;

    virtual void SetData(float a) = 0;

};

class CTriangle : public CShape {
private:
    float a, b, c;
public:
    void SetData(float a1, float b1, float c1);

    virtual void SetData(float a, float b) {};

    virtual void SetData(float a) {};

    float Area();

};

void CTriangle::SetData(float a1, float b1, float c1) {
    a = a1;
    b = b1;
    c = c1;

}

float CTriangle::Area() {
    float p = (a + b + c) / 2;
    float s = std::sqrt(p * (p - a) * (p - b) * (p - c));
    return s;
}

class CRect : public CShape {
private:
    float h, l;
public:
    void SetData(float a, float b) {
        h = a;
        l = b;
    }

    virtual void SetData(float a, float b, float c) {};

    virtual void SetData(float a) {};

    float Area() {
        return (float) h * l;
    }

};

class CCircle : public CShape {
private:
    float R;
public:
    void SetData(float a) {
        R = a;
    }

    float Area() {
        return (float) R * R * 3.1415926534;
    }

    virtual void SetData(float a, float b) {};

    virtual void SetData(float a, float b, float c) {};
};

class CArea {
private:
    std::vector<CShape *> S;
public:
    void AddShape(float a) {
        CShape *cs = new CCircle;
        cs->SetData(a);
        S.push_back(cs);
    }

    void AddShape(float a, float b) {
        CShape *cs = new CRect;
        cs->SetData(a, b);
        S.push_back(cs);
    }


    void AddShape(float a, float b, float c) {
        CShape *cs = new CTriangle;
        cs->SetData(a, b, c);
        S.push_back(cs);
    }

    float Sum() {
        float sum = 0;
        std::vector<CShape *>::iterator it;

        for (it = S.begin(); it != S.end(); it++) {
            sum += (*it)->Area();
        }
        return sum;
    }


};

//chapter4 book
class BaseClass {
public:
    virtual void fn1() {
        std::cout << "BaseClass_fn1" << std::endl;
    };

    void fn2() {

        std::cout << "BaseClass_fn2" << std::endl;
    };
};

class DerivedClass : public BaseClass {
public:
    void fn1() {

        std::cout << "DerivedClass_fn1" << std::endl;
    };

    void fn2() {

        std::cout << "DerivedClass_fn2" << std::endl;
    };
};


//add annotation q2
void out() {
    using namespace std;
    ofstream ofile;//定义文件类
    ofile.open("data.txt");//打开文件data.txt
    if (!ofile.fail()) {//如果成功打开文件
        ofile << "This is test data";//在文件内输入一段文字
        ofile.seekp(4);//改变输入文件的光标位置
        cout << ofile.tellp() << endl;//读取输入文件的光标位置
        ofile.close();//关闭文件

    } else//打开文件失败
        cout << "open output fail." << endl;

}

void in() {
    using namespace std;
    ifstream ifile("data.txt");//定义文件类，初始化为data.txt
    string s;//定义字符串
    if (!ifile.fail()) {//如果打开成功
        ifile.seekg(8);//改变文件输出光标的位置到第8个字符
        cout << ifile.tellg() << endl;//显示文件输出光标的位置
        ifile >> s;//输出文件内的字符串到s
        cout << ifile.tellg() << endl;//显示文件输出光标的位置
        cout << s << endl;//打印字符串s（This is test data）从第八个字符开始直到空格
    } else//如果打开失败
        cout << "open input fail." << endl;
}


int main() {
    CArea X;
    X.AddShape(1.0);
    X.AddShape(3, 6);
    X.AddShape(3, 4, 5);
    std::cout << X.Sum() << std::endl;
    X.AddShape(3.5);
    std::cout << X.Sum() << std::endl;

//chapter 4 book
    DerivedClass a;
    DerivedClass *pb = &a;
    BaseClass *pd = &a;
    pb->fn1();
    pb->fn2();
    pd->fn1();
    pd->fn2();
    //chapter 5 book
    int len = 6;
    for (int i = len; i > 0; i--) {
        char *s = new char[i + 1];
        for (int j = 0; j < i; j++) {
            s[j] = '*';
        }
        s[i] = '\0';
//        std::cout<<s<<std::endl;
        std::cout.setf(std::ios::right);
        std::cout << std::setw(len) << s;
        std::cout.unsetf(std::ios::right);
        std::cout << "*";
        std::cout.setf(std::ios::left);
        std::cout << std::setw(len) << s;

        std::cout.unsetf(std::ios::left);
//        std::cout<<"*";
        std::cout << std::endl;
//        std::cout<<s<<"?"<<std::endl;
        delete[] s;
    }

    std::cout.setf(std::ios::right);
    std::cout << std::setw(7) << "*" << std::endl;
    std::cout.unsetf(std::ios::right);


    //add annotation q1
    using namespace std;
    int x = 468;
    double y = -3.425648;
    cout << "x=" << setw(10) << x;//设置宽度为10输出x，默认为靠右输出
    cout << "y=" << setw(10) << y << endl;//同理y，换行
    cout << setiosflags(ios::left);//设置靠左输出
    cout << "x=" << setw(10) << x;//设置宽度为10，输出x（靠左）
    cout << "y=" << setw(10) << y << endl;//同理y，换行
    cout << setfill('*');//设置用*作为占位符填充没有输出的地方
    cout << setprecision(3);//设置输出精度为3
    cout << setiosflags(ios::showpos);//设置正数显示加号
    cout << "x=" << setw(10) << x;//输出x，宽度为10
    cout << "y=" << setw(10) << y << endl;//同理y，换行
    cout << resetiosflags(ios::left | ios::showpos);//取消靠左和显示正号
    cout << setfill(' ');//设置占位符号为空格
    //results
//    x=       468y=  -3.42565
//    x=468       y=-3.42565
//    x=+468******y=-3.43*****
    out();
    in();
//results
//    4
//    8
//    12
//    test

    return 0;
}